package com.kelab.dify.service.base;

import com.kelab.dify.config.DifyConfig;
import com.kelab.dify.exception.DifyApiException;
import com.kelab.dify.exception.DifyException;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

/**
 * 服务基类
 * 提供通用的HTTP请求处理和JSON序列化功能
 * 
 * @author kelab
 * @version 1.0
 */
public abstract class BaseService {
    
    private static final Logger logger = LoggerFactory.getLogger(BaseService.class);
    
    protected static final MediaType JSON_MEDIA_TYPE = MediaType.get("application/json; charset=utf-8");
    
    protected final OkHttpClient httpClient;
    protected final ObjectMapper objectMapper;
    protected final DifyConfig config;
    
    /**
     * 构造函数
     * 
     * @param httpClient HTTP客户端
     * @param objectMapper JSON映射器
     * @param config 配置信息
     */
    protected BaseService(OkHttpClient httpClient, ObjectMapper objectMapper, DifyConfig config) {
        this.httpClient = httpClient;
        this.objectMapper = objectMapper;
        this.config = config;
    }
    
    /**
     * 将对象转换为JSON字符串
     * 
     * @param object 要转换的对象
     * @return JSON字符串
     * @throws DifyException 如果转换失败
     */
    protected String toJson(Object object) throws DifyException {
        try {
            return objectMapper.writeValueAsString(object);
        } catch (Exception e) {
            throw new DifyException("Failed to serialize object to JSON", e);
        }
    }
    
    /**
     * 将JSON字符串转换为对象
     * 
     * @param json JSON字符串
     * @param clazz 目标类型
     * @param <T> 泛型类型
     * @return 转换后的对象
     * @throws DifyException 如果转换失败
     */
    protected <T> T fromJson(String json, Class<T> clazz) throws DifyException {
        try {
            return objectMapper.readValue(json, clazz);
        } catch (Exception e) {
            throw new DifyException("Failed to deserialize JSON to object", e);
        }
    }
    
    /**
     * 处理HTTP响应
     * 
     * @param response HTTP响应
     * @param clazz 响应对象类型
     * @param <T> 泛型类型
     * @return 响应对象
     * @throws DifyException 如果处理失败
     */
    protected <T> T handleResponse(Response response, Class<T> clazz) throws DifyException {
        try {
            String responseBody = response.body() != null ? response.body().string() : "";
            
            if (config.isEnableLogging()) {
                logger.debug("HTTP {} {}: {}", response.code(), response.request().url(), responseBody);
            }
            
            if (!response.isSuccessful()) {
                handleErrorResponse(response.code(), responseBody);
            }
            
            if (responseBody.isEmpty()) {
                throw new DifyException("Empty response body");
            }
            
            return fromJson(responseBody, clazz);
            
        } catch (IOException e) {
            throw new DifyException("Failed to read response body", e);
        }
    }
    
    /**
     * 处理错误响应
     * 
     * @param statusCode HTTP状态码
     * @param responseBody 响应体
     * @throws DifyApiException API异常
     */
    protected void handleErrorResponse(int statusCode, String responseBody) throws DifyApiException {
        String errorCode = "UNKNOWN_ERROR";
        String errorMessage = "Unknown error occurred";
        
        try {
            // 尝试解析错误响应
            ErrorResponse errorResponse = fromJson(responseBody, ErrorResponse.class);
            if (errorResponse != null) {
                errorCode = errorResponse.getCode() != null ? errorResponse.getCode() : errorCode;
                errorMessage = errorResponse.getMessage() != null ? errorResponse.getMessage() : errorMessage;
            }
        } catch (Exception e) {
            // 如果无法解析错误响应，使用原始响应体作为错误消息
            if (!responseBody.isEmpty()) {
                errorMessage = responseBody;
            }
        }
        
        throw new DifyApiException(statusCode, errorCode, errorMessage);
    }
    
    /**
     * 错误响应模型
     */
    public static class ErrorResponse {
        private String code;
        private String message;
        private String status;
        
        public String getCode() {
            return code;
        }
        
        public void setCode(String code) {
            this.code = code;
        }
        
        public String getMessage() {
            return message;
        }
        
        public void setMessage(String message) {
            this.message = message;
        }
        
        public String getStatus() {
            return status;
        }
        
        public void setStatus(String status) {
            this.status = status;
        }
    }
}